/*******************************************************************************
 * Copyright (c) 2012 laurent barbisan.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    laurent barbisan - initial API and implementation
 *******************************************************************************/ 

package fr.free.hd.servers.android.geonaute.connector;

import fr.free.hd.servers.android.geonaute.connector.devices.DeviceGH615;
import fr.free.hd.servers.android.geonaute.connector.model.DeviceInfo;
import fr.free.hd.servers.android.geonaute.connector.model.Track;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.os.AsyncTask;

public class LoadTrackInfoTask extends AsyncTask<LoadTrackInfoParams, Track, Void> {
	
	
	    private DeviceInfo info;
		private LoadTrackInfoParams loadTrackInfoParams;


		protected void onProgressUpdate(Track... progress) {
			loadTrackInfoParams.getAdapter().add(progress[0]);
	     }

	     protected void onPostExecute(Long result) {
	       
	     }

		@Override
		protected Void doInBackground(LoadTrackInfoParams... params) {
			
			loadTrackInfoParams = params[0];
			loadTrackInfoParams.setUsbConnection(loadTrackInfoParams.getUsbManager().openDevice(loadTrackInfoParams.getUsbDevice()));
			UsbInterface usbIf = DeviceGH615.initialize(loadTrackInfoParams.getUsbConnection(), loadTrackInfoParams.getUsbDevice(), loadTrackInfoParams.getUsbManager());
			loadTrackInfoParams.setEpIN(DeviceGH615.getInEndPoint(usbIf));
			loadTrackInfoParams.setEpOUT(DeviceGH615.getOutEndPoint(usbIf));
		
			info = getDeviceInfo(loadTrackInfoParams.getUsbConnection(), loadTrackInfoParams.getEpIN(), loadTrackInfoParams.getEpOUT());
			
			getTracksInfo(loadTrackInfoParams.getUsbConnection(), loadTrackInfoParams.getEpIN(), loadTrackInfoParams.getEpOUT(), info);
			
			return null;
		}
		
		
		 private DeviceInfo getDeviceInfo(UsbDeviceConnection connection, UsbEndpoint in, UsbEndpoint out)
		    {
		        byte[] command_b = new byte[5];
		        command_b[0] = (byte) 0x02;
		        command_b[1] = (byte) 0x00;
		        command_b[2] = (byte) 0x01;
		        command_b[3] = (byte) 0x85;
		        command_b[4] = (byte) 0x84;
		        
		        //Todo check timeout
		        connection.bulkTransfer(out, command_b, command_b.length, 500);

		        //The watch take time to answer
		        try {
					Thread.sleep(250);
				} catch (InterruptedException e) {
					
				}
		        
		        byte[] info = new byte[255];
		        //Todo check
		        connection.bulkTransfer(in, info, info.length, 100);
		        
		        int c = 0;
		        // Device name
		        c = 3;
		        DeviceInfo deviceInfo = new DeviceInfo();
		        deviceInfo.Device = "";
		        while (info[c] != 0) {
		            deviceInfo.Device += (char) info[c];
		            c++;
		        }

		        // User Name
		        c = 45;
		        deviceInfo.Name = "";
		        while (info[c] != 0) {
		            deviceInfo.Name += (char) info[c];
		            c++;
		        }

		        // User sex
		        if (info[56] == 0) {
		            deviceInfo.Sex = "Male";
		        } else {
		            deviceInfo.Sex = "Female";
		        }

		        // User age
		        deviceInfo.Age = DeviceGH615.uByteToInt(info[57]);

		        // User weight & height
		        deviceInfo.Weight_pounds = DeviceGH615.uByteToInt(info[59]);
		        deviceInfo.Weight_kg = DeviceGH615.uByteToInt(info[61]);
		        deviceInfo.Height_inch = DeviceGH615.uByteToInt(info[63]);
		        deviceInfo.Height_cm = Integer.valueOf(DeviceGH615.uByteToInt(info[65]));

		        // Tracks count
		        deviceInfo.TracksCount = DeviceGH615.uByteToInt(info[67]);

		        // Birth date
		        deviceInfo.Year = DeviceGH615.uByteToInt(info[69]) * 256 + DeviceGH615.uByteToInt(info[70]);
		        deviceInfo.Month = DeviceGH615.uByteToInt(info[71]);
		        deviceInfo.Day = DeviceGH615.uByteToInt(info[72]);
		        
		        return deviceInfo;

		    }
		 
		 
		 public void getTracksInfo(UsbDeviceConnection connection, UsbEndpoint in, UsbEndpoint out, DeviceInfo deviceInfo)
		    {
		        byte[] command_b = new byte[5];

		        command_b[0] = (byte) 0x02;
		        command_b[1] = (byte) 0x00;
		        command_b[2] = (byte) 0x01;
		        command_b[3] = (byte) 0x78;
		        command_b[4] = (byte) 0x79;
		        
		        //Todo check
		        connection.bulkTransfer(out, command_b, command_b.length, 500);

		        //The watch take time to answer
		        try {
					Thread.sleep(250);
				} catch (InterruptedException e) {
					
				}
		        
		        byte[] info = new byte[4096];
		        connection.bulkTransfer(in, info, info.length, 5000);

		        int trcount = 0;
		        int c;
		        while (trcount < deviceInfo.TracksCount) {
		            Track ti = new Track();

		            c = 3 + trcount * 31;

		            ti.Year = DeviceGH615.uByteToInt(info[c]) + 2000;
		            c++;
		            ti.Month = DeviceGH615.uByteToInt(info[c]);
		            c++;
		            ti.Day = DeviceGH615.uByteToInt(info[c]);
		            c++;
		            ti.Hour = DeviceGH615.uByteToInt(info[c]);
		            c++;
		            ti.Min = DeviceGH615.uByteToInt(info[c]);
		            c++;
		            ti.Sec = DeviceGH615.uByteToInt(info[c]);
		            c++;

		            ti.Laps = DeviceGH615.uByteToInt(info[c]);
		            c++;

		            ti.Duration_msec = DeviceGH615.uByteToInt(info[c]) * 16777216
		                    + DeviceGH615.uByteToInt(info[c + 1]) * 65536
		                    + DeviceGH615.uByteToInt(info[c + 2]) * 256
		                    + DeviceGH615.uByteToInt(info[c + 3]);
		            c++;
		            c++;
		            c++;
		            c++;
		            ti.Duration_h = (ti.Duration_msec / 36000);
		            ti.Duration_m = (ti.Duration_msec - ti.Duration_h * 36000) / 600;
		            ti.Duration_s = (ti.Duration_msec - ti.Duration_h * 36000 - ti.Duration_m * 600) / 10;

		            ti.Duration_msec = ti.Duration_msec * 10;

		            ti.Distance =
		                    DeviceGH615.uByteToInt(info[c]) * 16777216
		                    + DeviceGH615.uByteToInt(info[c + 1]) * 65536
		                    + DeviceGH615.uByteToInt(info[c + 2]) * 256
		                    + DeviceGH615.uByteToInt(info[c + 3]);
		            c++;
		            c++;
		            c++;
		            c++;

		            if(ti.Duration_msec!=0)
		            	ti.AvgSpeed = (double) (3600 * ti.Distance / ti.Duration_msec) / 100;

		            ti.Calories = DeviceGH615.uByteToInt(info[c]) * 256 + DeviceGH615.uByteToInt(info[c + 1]);
		            c++;
		            c++;

		            ti.TopSpeed = (double) (DeviceGH615.uByteToInt(info[c]) * 256 + DeviceGH615.uByteToInt(info[c + 1])) / 100;
		            c++;
		            c++;

		            ti.TopHeartBeat = DeviceGH615.uByteToInt(info[c]);
		            c++;

		            ti.AvgHeartBeat = DeviceGH615.uByteToInt(info[c]);
		            c++;

		            ti.AscHeight = DeviceGH615.uByteToInt(info[c]) * 256 + DeviceGH615.uByteToInt(info[c + 1]);
		            c++;
		            c++;

		            ti.DescHeight = DeviceGH615.uByteToInt(info[c]) * 256 + DeviceGH615.uByteToInt(info[c + 1]);
		            c++;
		            c++;

		            ti.Points = DeviceGH615.uByteToInt(info[c]) * 256 + DeviceGH615.uByteToInt(info[c + 1]);
		            c++;
		            c++;

		            ti.ID = DeviceGH615.uByteToInt(info[c]) * 256 + DeviceGH615.uByteToInt(info[c + 1]);

		            publishProgress(ti);
		            trcount++;
		        }
		    }

}
